#include <stdexcept>
#include <fstream>
#include <iostream>
#include <sys/time.h>
#include "pub_defs.h"

TD::TD(double a, double b, double c) : x(a), y(b), z(c) {}

TD TD::operator+(const TD& other) const {
    return TD(x+other.x, y+other.y, z+other.z);
}

TD TD::operator-(const TD& other) const {
    return TD(x-other.x, y-other.y, z-other.z);
}

TD TD::operator*(double a) const {
    return TD(x*a, y*a, z*a);
}

TD TD::operator/(double a) const {
    if (a == 0) {
        throw std::runtime_error("division by zero");
    }
    return TD(x/a, y/a, z/a);
}

bool TD::operator==(const TD& other) const {
    return std::abs(x-other.x) < 1e-10 && std::abs(y-other.y) < 1e-10 && std::abs(z-other.z) < 1e-10;
}

/**
 * @brief 写入输入文件
 */
int write_infile(TD* x, TD* v, int n) {
    std::ofstream infile("input.bin", std::ios::binary);
    if (!infile) {
        return 1;
    }
    infile.write(reinterpret_cast<const char*>(x), n * sizeof(TD));
    infile.write(reinterpret_cast<const char*>(v), n * sizeof(TD));

    infile.close();
    return 0;
}

int write_outfile(TD* x, TD* v, int n) {
     std::ofstream outfile("output.bin", std::ios::binary);
    if (!outfile) {
        return 1;
    }
    outfile.write(reinterpret_cast<const char*>(x), n * sizeof(TD));
    outfile.write(reinterpret_cast<const char*>(v), n * sizeof(TD));

    outfile.close();
    return 0;
}

/**
 * @brief 读取输入文件
*/
int read_infile(TD* x, TD* v, int n) {
    std::ifstream infile("input.bin", std::ios::binary);
    if (!infile) {
        return 1;
    }
    infile.read(reinterpret_cast<char*>(x), n*sizeof(TD));
    infile.read(reinterpret_cast<char*>(v), n*sizeof(TD));

    infile.close();
    return 0;
}

int read_outfile(TD* x, TD* v, int n) {
    std::ifstream outfile("output.bin", std::ios::binary);
    if (!outfile) {
        return 1;
    }
    outfile.read(reinterpret_cast<char*>(x), n*sizeof(TD));
    outfile.read(reinterpret_cast<char*>(v), n*sizeof(TD));

    outfile.close();
    return 0;
}

double wall_time() {
    struct timeval tv;
    gettimeofday(&tv, nullptr);
    return tv.tv_sec + 1e-6*tv.tv_usec;
}

template<typename T>
bool compare_array(T* a, T* b, int n) {
    for (int i = 0; i < n; i++) {
        if (a[i]==b[i]){
            continue;
        }
        return false;
    }
    return true;
}

template bool compare_array<TD>(TD*, TD*, int);
